package com.atguigu.boot.config;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zp
 * @version 1.0
 * @description: 全局异常扫描
 * 总共有三种配置异常处理的方式
 * 1、在controller 直接使用@ExceptionHandler(ArithmeticException.class) 定义一个方法 设置异常拦截类型
 *    配合@ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE) 可以设置响应码
 * 2、使用@ControllerAdvice 定义一个全局的错误处理controller 也是使用
 *  1.@ExceptionHandler(NullPointerException.class)
 *  2.@ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
 *  两个注解配合使用
 * 3、实现HandlerExceptionResolver 自定义错误消息处理器 (如果需要测试自定义异常处理器 需要注释前面俩个自定义异常处理的方法)
 * 或者实现Ordered接口 实现getOrder方法 值为-1
 *
 * 三种实现方法的默认执行顺序：
 * 1、自定义在controller层 使用@ExceptionHandler 执行优先级最高 如果定义了Exception拦截在最前面 其他异常不会被捕获
 * 2、使用@ControllerAdvice 全局扫描异常注解 定义拦截类型 如果在controller层已经定义了拦截 默认这里的方法不会执行 优先级靠后
 * 3、自定义错误处理器实 现HandlerExceptionResolver 在最后执行 因为前面先检查有没有@ExceptionHandler 注解自定义的异常处理
 * 然后有一个系统默认的 HandlerExceptionResolver 最后才会轮到自定义的异常处理器
 * 不过可以使用实现Ordered接口的方式自定义执行顺序 实现getOrder方法 值为-1 就可以使自定义的异常处理器第一个执行
 *
 * 底层有几个东西需要了解
 * ExceptionHandlerExceptionResolver 默认实现的异常处理器
 * ErrorViewResolver 视图异常处理
 * 最后会转到BasicErrorController 处理未被任何自定义异常处理器，或者其他异常处理方案处理的异常
 * 通过这个Controller来完成兜底的方案
 * 默认实现 如果探查到handle处理出现异常 如果没有相关处理 是先抛出然后把异常信息保存到请求头 然后转发到默认的 /error这个地址
 * BasicErrorController：@RequestMapping("${server.error.path:${error.path:/error}}")
 * 也是BasicErrorController类默认的路径 可以再yaml里面配置 错误页面的位置
 * 默认也是通过内容协商机制 动态的返回 HTML页面还是JSON数据
 *
 * @date 2022/9/19 19:06
 */
@ControllerAdvice
@ResponseBody
public class ErrorConfig {

    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    public Map<String,Object> getNullPointerException(Exception exception){
        Map<String,Object> map = new HashMap<>();
        map.put("type","NullPointerException");
        map.put("date",new Date());
        map.put("ex",exception.getMessage());
        return map;
    }

    @ExceptionHandler(ArithmeticException.class)
    public Map<String,Object> getConfigArithmeticException(Exception exception){
        Map<String,Object> map = new HashMap<>();
        map.put("type","NullPointerException ErrorConfig");
        map.put("date",new Date());
        map.put("ex",exception.getMessage());
        return map;
    }


}
